Skip to content

Multi project support for the C# parser#847

Open
HorvathDaniel15 wants to merge 2 commits intoEricsson:feature/csharp_pluginfrom
HorvathDaniel15:feature/support-multi-project-csharp-parser
Open

Multi project support for the C# parser#847
HorvathDaniel15 wants to merge 2 commits intoEricsson:feature/csharp_pluginfrom
HorvathDaniel15:feature/support-multi-project-csharp-parser

Conversation

@HorvathDaniel15
Copy link
Copy Markdown
Collaborator

@HorvathDaniel15 HorvathDaniel15 commented Apr 4, 2026

Resolves #823

Copilot AI review requested due to automatic review settings April 4, 2026 18:02
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the C# parser to accept richer inputs (solutions/projects) and to better handle multiple inputs, enabling “multi-project” parsing via Roslyn/MSBuild rather than only directory-based discovery.

Changes:

  • Add input validation and safer log parsing in the C++ wrapper (avoid empty-input and empty-line crashes; log non file-status output).
  • Update the C# parser to support .sln/.slnx and .csproj inputs using MSBuildWorkspace, with a fallback path that extracts project paths from solution files.
  • Add Roslyn MSBuild workspace dependency and ignore .DS_Store.

Reviewed changes

Copilot reviewed 3 out of 4 changed files in this pull request and generated 7 comments.

File Description
plugins/csharp/parser/src/csharpparser.cpp Validates inputs and hardens parsing of the C# parser output stream.
plugins/csharp/parser/src_csharp/Program.cs Implements solution/project loading via MSBuildWorkspace and multi-project processing with parallel document parsing.
plugins/csharp/parser/src_csharp/CSharpParser.csproj Adds Microsoft.CodeAnalysis.Workspaces.MSBuild to support solution/project loading.
.gitignore Ignores macOS .DS_Store.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +26 to 30
static async Task<int> Main(string[] args)
{
MSBuildLocator.RegisterDefaults();
_rootDir = new List<string>();
int threadNum = 4;
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MSBuildLocator.RegisterDefaults() can throw (e.g., when no compatible MSBuild instance is found), which would currently crash the process before you emit any parser-friendly error output. Wrap registration in the existing argument-parsing try/catch (or a dedicated try/catch) and return a non-zero exit code with a clear message when registration fails.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This thread was resolved, but no fix is present in the codebase.

Comment on lines 89 to 96
string csharpConnectionString = transformConnectionString();

var options = new DbContextOptionsBuilder<CsharpDbContext>()
.UseNpgsql(csharpConnectionString)
.Options;

CsharpDbContext _context = new CsharpDbContext(options);
_context.Database.Migrate();
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The database context is created and migrations are applied before validating that any input paths were provided. This can cause unnecessary (and potentially destructive/slow) DB work even when the CLI invocation is invalid; consider validating args/_rootDir first, then migrating/creating the DbContext only for valid runs (and disposing it via using/await using).

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This thread was resolved, but no fix is present in the codebase.

Comment on lines +131 to +132
Console.Error.WriteLine($"Unsupported file type: {primaryInput}");
Console.Error.WriteLine("Supported: .sln, .slnx, .csproj");
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code writes important user-facing errors to stderr, but the C++ wrapper currently captures only stdout (bp::std_out > log). As a result, failures/diagnostics may be invisible to the caller. Consider writing these diagnostics to stdout (with a prefix) or ensure stderr is also captured/redirected by the wrapper.

Suggested change
Console.Error.WriteLine($"Unsupported file type: {primaryInput}");
Console.Error.WriteLine("Supported: .sln, .slnx, .csproj");
WriteLine($"ERROR: Unsupported file type: {primaryInput}");
WriteLine("ERROR: Supported: .sln, .slnx, .csproj");

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can keep it the current way, but this static usage for System.Console is quite odd. Please remove that and instead write Console.WriteLine() on each usage for clarity and convention purposes.

Comment thread plugins/csharp/parser/src_csharp/Program.cs Outdated
Comment on lines +487 to +517
private static async Task<Solution> LoadInputAsync(string inputPath)
{
if (File.Exists(inputPath))
{
if (inputPath.EndsWith(".sln", StringComparison.OrdinalIgnoreCase) ||
inputPath.EndsWith(".slnx", StringComparison.OrdinalIgnoreCase))
{
return await LoadSolutionAsync(inputPath);
}
if (inputPath.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase))
{
return await LoadProjectAsync(inputPath);
}
else
{
Console.Error.WriteLine($"Unsupported file type: {inputPath}");
Console.Error.WriteLine("Supported: .sln, .slnx, .csproj");
return null;
}
}
if (Directory.Exists(inputPath))
{
return null;
}
else
{
Console.Error.WriteLine($"Input path not found: {inputPath}");
return null;
}
}

Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LoadInputAsync is not referenced anywhere in the file (no call sites). Keeping this unused method (and its error-printing branches) adds dead code and increases maintenance surface. Either remove it or refactor Main to use it so there is a single, tested input-loading pathway.

Suggested change
private static async Task<Solution> LoadInputAsync(string inputPath)
{
if (File.Exists(inputPath))
{
if (inputPath.EndsWith(".sln", StringComparison.OrdinalIgnoreCase) ||
inputPath.EndsWith(".slnx", StringComparison.OrdinalIgnoreCase))
{
return await LoadSolutionAsync(inputPath);
}
if (inputPath.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase))
{
return await LoadProjectAsync(inputPath);
}
else
{
Console.Error.WriteLine($"Unsupported file type: {inputPath}");
Console.Error.WriteLine("Supported: .sln, .slnx, .csproj");
return null;
}
}
if (Directory.Exists(inputPath))
{
return null;
}
else
{
Console.Error.WriteLine($"Input path not found: {inputPath}");
return null;
}
}

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HorvathDaniel15 Is this really dead code, or Copilot just did not find its usage?

Comment on lines +598 to +606

foreach (var group in documentGroups)
{
tasks.Add(Task.Run(async () =>
{
var options = new DbContextOptionsBuilder<CsharpDbContext>()
.UseNpgsql(csharpConnectionString)
.Options;
var localDbContext = new CsharpDbContext(options);
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

localDbContext is created inside each worker task but never disposed. Since DbContext holds pooled connections and unmanaged resources, this can leak connections under load. Use (await) using for the context (and consider creating options once outside the loop).

Suggested change
foreach (var group in documentGroups)
{
tasks.Add(Task.Run(async () =>
{
var options = new DbContextOptionsBuilder<CsharpDbContext>()
.UseNpgsql(csharpConnectionString)
.Options;
var localDbContext = new CsharpDbContext(options);
var options = new DbContextOptionsBuilder<CsharpDbContext>()
.UseNpgsql(csharpConnectionString)
.Options;
foreach (var group in documentGroups)
{
tasks.Add(Task.Run(async () =>
{
await using var localDbContext = new CsharpDbContext(options);

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This thread was resolved, but no fix is present in the codebase. Please provide a counter-argument if no code change is required.

Comment thread plugins/csharp/parser/src_csharp/Program.cs
@mcserep mcserep added Kind: Enhancement 🌟 Plugin: C# Issues related to the parsing and presentation of C# projects. labels Apr 14, 2026
@mcserep mcserep added this to Lab and Roadmap Apr 14, 2026
@mcserep mcserep changed the title Implement support multi projet for the csharp parser Multi project support for the C# parser Apr 14, 2026
@github-project-automation github-project-automation Bot moved this to In progress in Lab Apr 14, 2026
@github-project-automation github-project-automation Bot moved this to In progress in Roadmap Apr 14, 2026
@mcserep mcserep self-requested a review April 14, 2026 09:08
@mcserep mcserep linked an issue Apr 14, 2026 that may be closed by this pull request
@mcserep mcserep added this to the Upcoming Release milestone Apr 14, 2026
@mcserep mcserep requested a review from Copilot April 21, 2026 09:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 4 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +520 to +523
Console.WriteLine($"Loading solution: {solutionPath}");
var workspace = CreateMsBuildWorkspace();

var solution = await workspace.OpenSolutionAsync(solutionPath);
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MSBuildWorkspace created here is not disposed. Since loading a solution can allocate significant resources, this can cause avoidable memory/file-handle usage. Wrap the workspace in a using/await using (or otherwise ensure Dispose() is called) once loading is complete.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid memory optimization concern.

if (projectPaths.Count == 0)
{
Console.Error.WriteLine($"No C# projects found in solution: {solutionPath}");
return;
Copy link

Copilot AI Apr 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When no C# projects are found in the solution, this method logs an error and returns, but Main will still exit with code 0. That makes the wrapper/parser treat the run as successful even though nothing was parsed. Consider propagating failure (e.g., return a bool/int result or throw) so Main can exit non-zero in this case.

Suggested change
return;
throw new InvalidOperationException(
$"No C# projects found in solution: {solutionPath}");

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Valid concern, since in case of other input errors, the program return with a non-zero exit code.

Comment thread plugins/csharp/parser/src/csharpparser.cpp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Kind: Enhancement 🌟 Plugin: C# Issues related to the parsing and presentation of C# projects.

Projects

Status: In progress
Status: In progress

Development

Successfully merging this pull request may close these issues.

Support multi-project parsing for the C# plugin

4 participants